use ane_system::dao::{LoginLogVo, SysLog};
use axum::{
    extract::{Path, Query},
    response::IntoResponse,
    routing::get,
    Extension, Router,
};
use common::page::PageInfo;
use sea_orm::{EntityTrait, QueryFilter};

use crate::{error::AppResult, extract::Json, security::LoginUser, state::AppState};

use super::SysFilter;

/// 日志操作相关的路由
/// - `{prefix}/login` `GET|DELETE` [LoginLog](ane_system::entity::sys_login_log)的查询和删除
/// - `{prefix}/operate` `GET|DELETE` [OperateLog](ane_system::entity::sys_operate_log)的查询和删除
pub fn get_route<S>(prefix: &str) -> Router<S>
where
    S: Sync + Send + Clone + 'static,
{
    let f = move |p: &str| -> String { format!("{}{p}", prefix) };
    #[cfg_attr(rustfmt, rustfmt_skip)]
    Router::<S>::new()
        .route(&f("/login"), get(login_log_list).delete(login_log_delete))
        .route(&f("/operate"),get(operate_log_list).delete(operate_log_delete))
}

pub async fn login_log_list(
    Extension(state): Extension<AppState>,
    Query(filter): Query<SysFilter>,
) -> AppResult<impl IntoResponse> {
    SysLog::list_login::<LoginLogVo>(
        state.db(),
        filter.page.zero_page(),
        filter.page.page_size(),
        filter.username,
        filter.result,
    )
    .await
    .map(|(datas, total)| Json(PageInfo::new(datas, &filter.page, total)))
    .map_err(Into::into)
}

pub async fn login_log_delete(
    Extension(state): Extension<AppState>,
    Path(id): Path<i32>,
) -> AppResult<impl IntoResponse> {
    SysLog::del_login_log(state.db(), id)
        .await
        .map(Json)
        .map_err(Into::into)
}

pub async fn operate_log_list(
    Extension(state): Extension<AppState>,
    Query(filter): Query<SysFilter>,
    user: LoginUser,
) -> AppResult<impl IntoResponse> {
    SysLog::list_operate(
        state.db(),
        filter.page.zero_page(),
        filter.page.page_size(),
        filter.result,
        Some(user.dept_cond()),
    )
    .await
    .map(|(total, datas)| Json(PageInfo::new(datas, &filter.page, total)))
    .map_err(Into::into)
}

pub async fn operate_log_delete(
    Extension(state): Extension<AppState>,
    Path(id): Path<i32>,
    user: LoginUser,
) -> AppResult<impl IntoResponse> {
    use ane_system::entity::sys_operate_log;
    use sea_orm::ColumnTrait;
    sys_operate_log::Entity::delete_by_id(id)
        .filter(sys_operate_log::Column::OperatorId.in_subquery(user.sub_user()))
        .exec(state.db())
        .await
        .map(|e| e.rows_affected > 0)
        .map(Json)
        .map_err(Into::into)
}
